package com.atguigu01.example;

import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;

/**
 * ClassName: ReflectionTest
 * Description:
 *
 * @Author liu
 * @Create 2025/4/26 15:44
 * @Version 1.0
 */
public class ReflectionTest {
    /**
     * 使用反射之前可以执行的操作
     */
    @Test
    public void test1(){
      //1.创建Person类的实例
        //public Person()
        Person p1 = new Person();
        System.out.println(p1);

      //2.调用属性
      //public int age
      p1.age = 10;
      System.out.println(p1.age);

      //3.调用方法
      //public void show()
      p1.show();
    }

    /**
     * 使用反射完成上述的操作
     * 用于public
     */
    @Test
    public void test2() throws Exception{
        //1.创建Person实例
        //public Person
        Class<Person> clazz = Person.class;
        Person p1 = clazz.newInstance();
        System.out.println(p1);
        //或
        Class clazz1 = Person.class;
        Person p2 = (Person) clazz1.newInstance();
        System.out.println(p2);


        //2.调用属性
        //public int age
        Field ageField = clazz.getField("age");
        ageField.set(p1,10);
        System.out.println(ageField.get(p1));


        //3.调用方法
        //public void show()
        Method showMethod = clazz.getMethod("show");
        showMethod.invoke(p1);

    }

    /**
     * 用于private
     *出了Person类之后，就不能直接调用Person类中声明的private权限修饰的结构（属性、方法、构造器）
     * 但是，我们可以通过反射的方式，调用Person类中私有的结构  ---> 暴力反射
     */

    @Test
    public void test3() throws Exception {
        //1.调用私有的构造器，创建person得实例
        //private Person(String name,int age)
        Class<Person> clazz = Person.class;
        //属性用 数据类型.class 代入
        Constructor<Person> cons = clazz.getDeclaredConstructor(String.class, int.class);
        //确保此属性是可以访问的
        cons.setAccessible(true);
        Person p1 = cons.newInstance("tom",12);
        System.out.println(p1);


        //2.调用属性
        //private String name;
        Field nameField = clazz.getDeclaredField("name");
        nameField.setAccessible(true);
        nameField.set(p1,"Jerry");
        System.out.println(nameField.get(p1));


        //3.调用私有方法
        //private String showNation(String namtion)
        Method showNation = clazz.getDeclaredMethod("showNation", String.class);
        showNation.setAccessible(true);
        String info = (String) showNation.invoke(p1, "chn");
        System.out.println(info);
    }
}
